package com.iweb.zuul.filters;

import cn.hutool.core.util.StrUtil;
import com.iweb.zuul.rsa.RsaKeys;
import com.iweb.zuul.service.RsaService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class EncryptFilter extends ZuulFilter {

    @Autowired
    private RsaService rsaService;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 2;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @SneakyThrows
    @Override
    public Object run() {
        log.info("解密网关拦截");

        // 获取 HttpServletRequest
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        // 获取请求体
        ServletInputStream in = request.getInputStream();
        String encryptData = StreamUtils.copyToString(in, StandardCharsets.UTF_8);
        log.info("加密后的参数:{}", encryptData);

        // 如果请求参数为空则无序解密
        if (StrUtil.isEmpty(encryptData)) {
            return null;
        }
        // 解密请求参数
        String decryptData = rsaService.RSADecryptDataPEM(encryptData,
                RsaKeys.getServerPrvKeyPkcs8());
        log.info("解密后的数据:{}", decryptData);
        // 重新封装请求
        final byte[] reqBodyBytes = decryptData.getBytes();
        // 设置请求 数据
        context.setRequest(new HttpServletRequestWrapper(request) {
            @Override
            public ServletInputStream getInputStream() {
                return new ServletInputStreamWrapper(reqBodyBytes);
            }

            @Override
            public int getContentLength() {
                return reqBodyBytes.length;
            }

            @Override
            public long getContentLengthLong() {
                return reqBodyBytes.length;
            }
        });

        // 设置请求头
        context.addZuulRequestHeader("Content-Type",
                MediaType.APPLICATION_JSON + ";charset=UTF-8");
        return null;
    }
}
